/*
** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/

#ifndef lobject_h
#define lobject_h


#include <stdarg.h>

#include "llimits.h"
#include "lua.h"


/* tags for values visible from Lua */
#define LAST_TAG	LUA_TTHREAD


/*
** Extra tags for non-values
*/
#define LUA_TDEADKEY	(LAST_TAG+3)


/*
** Union of all collectable objects
*/
typedef union GCObject GCObject;


/*
** Common Header for all collectable objects (in macro form, to be
** included in other objects)
** next: point to next member in GC chain list
** tt: type of data
** marked: mark for GC
*/
#define CommonHeader	GCObject *next; lu_byte tt; lu_byte marked


/*
** Common header in struct form
*/
typedef struct GCHeader{
	CommonHeader;
}GCHeader;


/*
**	Union of all lua values(GCObject and not GCObject)
**	gc: point to GCObject
**	p:	type: LUA_TLIGHTUSERDATA
**	n:	lua_Number data, type: LUA_TNUMBER
**	b:	bool data, type: LUA_TBOOLEAN
*/
typedef union{
	GCObject *gc;
	void *p;
	lua_Number n;
	int b;
}Value;


/*
**	Tagged Values
**	tt: type of data
*/
#define TValuefields	Value value; int tt

typedef struct lua_TValue{
	TValuefields;
}TValue;


/* Macros to test type */
#define ttisnil(o)	(ttype(o) == LUA_TNIL)
#define ttisnumber(o)	(ttype(o) == LUA_TNUMBER)
#define ttisstring(o)	(ttype(o) == LUA_TSTRING)
#define ttisboolean(o)	(ttype(o) == LUA_TBOOLEAN)
#define ttislightuserdata(o)	(ttype(o) == LUA_TLIGHTUSERDATA)


/* Macros to access values */
#define ttype(o)	((o)->tt)
#define gcvalue(o)	check_exp(iscollectable(o), (o)->value.gc)
#define pvalue(o)	check_exp(ttislightuserdata(o), (o)->value.p)
#define nvalue(o)	check_exp(ttisnumber(o), (o)->value.n)
#define rawtsvalue(o)	check_exp(ttisstring(o), &(o)->value.gc->ts)
#define bvalue(o)	check_exp(ttisboolean(o), (o)->value.b)


/*
** for internal debug only
*/
#define checkliveness(g, obj) \
	lua_assert(!iscollectable(obj2) || \
	((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))


/* Macros to set values */
#define setnilvalue(obj)	((obj)->tt=LUA_TNIL)

#define setnvalue(obj, x) \
	{ TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }

#define setsvalue(L, obj, x) \
	{ TValue *i_o=(obj); \
	  i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \
	  checkliveness(G(L), i_o); }


#define setobj(L, obj1, obj2) \
	{ const TValue *o2=(obj2); TValue *o1=(obj1); \
	  o1->value = o2->value; o1->tt=o2->tt; \
	  checkliveness(G(L), o1); }


/*
** different types of sets, according to destination
*/

/* from table to same table */
#define setobjt2t	setobj
/* to stack (not from same stack) */
#define setobj2s	setobj


#define iscollectable(o)	(ttype(o) >= LUA_TSTRING)


typedef TValue *StkId;	/* index to stack elements */


/*
**	String headers for string table
*/
typedef union TString {
	L_Umaxalign dummy;	/* ensure maximum alignment for strings */
	struct{
		CommonHeader;
		lu_byte reserved;	/* is reserved word or not */
		unsigned int hash;	/* hash of string */
		size_t len;	/* length of string */
	}tsv;
}TString;


#define getstr(ts)	cast(const char *, (ts) + 1)


typedef union Udata {

}Udata;


/*
** Function Prototypes
*/
typedef struct Proto {

}Proto;


/*
**	Upvalues
*/
typedef struct UpVal {

}UpVal;


typedef union Closure {

}Closure;


/*
**	Tables
*/

typedef union TKey{
	struct {
		TValuefields;
		struct Node *next;	/* for chaining */
	}nk;
	TValue tvk;
}TKey;


typedef struct Node{
	TValue i_val;
	TKey i_key;
}Node;


typedef struct Table {
	CommonHeader;
	lu_byte flags;	/* 1<<p means tagmethod(p) is not present */
	lu_byte lsizenode;	/* log2 of size of `node' array */
	struct Table* metatable;
	TValue *array;	/* array part */
	Node *node;	/* the point to the first position of hashtable */
	Node *lastfree;	/* any free position is before this position */
	GCObject *gclist;
	int sizearray;	/* size of `array' array */
}Table;


/*
** `module' operation for hashing (size is always a power of 2)
*/
#define lmod(s, size) \
	(check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1)))))


#define twoto(x)	(1<<(x))
#define sizenode(t)	(twoto((t)->lsizenode))


#define ceillog2(x)	(luaO_log2((x)-1) + 1)

#define luaO_nilobject 	(&luaO_nilobject_)

LUAI_DATA const TValue luaO_nilobject_;

LUAI_FUNC int luaO_log2 (unsigned int x);
LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);


#endif
